﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace Liquid.Windows.Commands {
	public class Command : Component {
		public Command() : this("Command") { }
		public Command(string name) { this.Name = name; }

		[DefaultValue("Command")]
		public string Name {
			get { return m_Name; }
			set {
				m_Name = value;
				if (DesignMode && Site != null && m_Name != null)
					Site.Name = string.Format(
						"command_{0}",
						m_Name.Replace('.', '_')
					);
			}
		}
		string m_Name;

		public string Text {
			get { return m_Text; }
			set {
				if (m_Text != value) {
					m_Text = value;
					OnTextChanged(EventArgs.Empty);
				}
			}
		}
		string m_Text;
		private void OnTextChanged(EventArgs e) {
			foreach (var binding in Bindings) {
				binding.OnTextChanged(e);
			}
		}

		public string ToolTipText {
			get { return m_ToolTipText; }
			set {
				if (m_ToolTipText != value) {
					m_ToolTipText = value;
					OnToolTipTextChanged(EventArgs.Empty);
				}
			}
		}
		string m_ToolTipText;
		protected virtual void OnToolTipTextChanged(EventArgs e) {
			foreach (var binding in Bindings) {
				binding.OnToolTipTextChanged(e);
			}
		}

		public Image DefaultImage {
			get { return m_DefaultImage; }
			set {
				if (m_DefaultImage != value) {
					m_DefaultImage = value;
					OnDefaultImageChanged(EventArgs.Empty);
				}
			}
		}
		Image m_DefaultImage;
		private void OnDefaultImageChanged(EventArgs e) {
			foreach (var binding in Bindings) {
				binding.OnImageChanged(e);
			}
		}

		public bool Enabled {
			get { return m_Enabled; }
			set {
				if (m_Enabled != value) {
					m_Enabled = value;
					OnEnabledChanged(EventArgs.Empty);
				}
			}
		}
		bool m_Enabled = true;
		private void OnEnabledChanged(EventArgs e) {
			foreach (var binding in Bindings) {
				binding.OnEnabledChanged(e);
			}
		}

		public CheckState CheckedState {
			get { return m_CheckedState; }
			set {
				if (m_CheckedState != value) {
					m_CheckedState = value;
					OnCheckedStateChanged(EventArgs.Empty);
				}
			}
		}
		CheckState m_CheckedState;
		private void OnCheckedStateChanged(EventArgs e) {
			foreach (var binding in Bindings) {
				binding.OnCheckedStateChanged(e);
			}
		}

		public bool Checked {
			get { return CheckedState == CheckState.Checked; }
			set { CheckedState = value ? CheckState.Checked : CheckState.Unchecked; }
		}

		public bool CheckOnActivate { get; set; }

		public void Activate(CancelEventArgs e) {
			if (CheckOnActivate)
				Checked = !Checked;
			OnActivated(e);
			if (CheckOnActivate && e.Cancel)
				Checked = !Checked;
		}

		public event CancelEventHandler Activated;
		private void OnActivated(CancelEventArgs e) {
			var handler = Activated;
			if (handler != null)
				handler(this, e);
		}

		public ReadOnlyCollection<CommandBinding> Bindings { get { return m_Bindings.AsReadOnly(); } }
		private List<CommandBinding> m_Bindings = new List<CommandBinding>();

		public void AddBinding(CommandBinding binding) {
			if (binding.Command != null)
				throw new NotSupportedException();
			if (m_Bindings.Contains(binding))
				return;
			m_Bindings.Add(binding);
			binding.Command = this;
			binding.Bind();
		}
		public void RemoveBinding(CommandBinding binding) {
			if (m_Bindings.Remove(binding))
				binding.Command = null;
		}

		internal CommandSet CommandSet {
			get {
				var target = m_CommandSet == null
					? null
					: m_CommandSet.Target;
				return (CommandSet)target;
			}
			set {
				if (value == null)
					m_CommandSet = null;
				else
					m_CommandSet = new WeakReference(value);
			}
		}
		private WeakReference m_CommandSet;

		public override string ToString() {
			return string.Format("{0} - {1}", Name, GetHashCode());
		}
	}
}
